package view.dialog;

import java.util.Calendar;
import java.util.LinkedList;

import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.SpinnerListModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import model.Expense;
import model.Income;
import model.Model;
import model.Transfer;
import connectors.DataSource;
import controller.Controller;

@SuppressWarnings("serial")
public class TransactionForm extends JPanel {

	private Controller controller;
	private DefaultComboBoxModel<Object> categoryBoxModel;
	private DefaultComboBoxModel<String> accountBoxModel;
	private ButtonGroup btnGroup;
	private JRadioButton rdbtnAusgabe;
	private JRadioButton rdbtnEinkommen;
	private JRadioButton rdbtnUmbuchung;
	private JComboBox<Object> categoryBox;
	private JComboBox<String> venueField;
	private JSpinner daySpinner;
	private JSpinner monthSpinner;
	private JSpinner yearSpinner;
	private JSpinner amountSpinner;
	private JComboBox<String> accountComboBox;
	private ChangeListener rdbtnListener;
	private JLabel lblZielkonto;
	private JComboBox<String> targetAccountBox;
	private JLabel lblBemerkung;
	private JComboBox<String> commentComboBox;
	private DefaultComboBoxModel<String> commentComboBoxModel;
	private DefaultComboBoxModel<String> targetAccountBoxModel;
	private JLabel lblOrt;
	private JLabel lblKategorie;
	private JSeparator separator;
	
	

	/**
	 * Create the panel.
	 * @param controller 
	 */
	public TransactionForm(Controller controller) {
		this.controller = controller;
		
		rdbtnListener = new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				if(rdbtnAusgabe.isSelected()) {
					switchForm(true, false, false);
				}
				else if(rdbtnEinkommen.isSelected()) {
					switchForm(false, true, false);
				}
				else if(rdbtnUmbuchung.isSelected()) {
					switchForm(false, false, true);
				}
			}
		};
		
		btnGroup = new ButtonGroup();
		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		
		rdbtnAusgabe = new JRadioButton("Ausgabe");
		
		rdbtnAusgabe.setSelected(true);
		btnGroup.add(rdbtnAusgabe);
		add(rdbtnAusgabe);
		
		rdbtnEinkommen = new JRadioButton("Einkommen");
		
		btnGroup.add(rdbtnEinkommen);
		add(rdbtnEinkommen);
		
		rdbtnUmbuchung = new JRadioButton("Umbuchung");
		
		btnGroup.add(rdbtnUmbuchung);
		add(rdbtnUmbuchung);
		
		separator = new JSeparator();
		add(separator);
		
		lblKategorie = new JLabel("Kategorie");
		lblKategorie.setHorizontalAlignment(SwingConstants.CENTER);
		add(lblKategorie);
		
		categoryBox = new JComboBox<Object>();
		categoryBoxModel = new DefaultComboBoxModel<Object>();
		parseCategories();
		categoryBox.setModel(categoryBoxModel);
		add(categoryBox);
		
		lblOrt = new JLabel("Ort");
		lblOrt.setHorizontalAlignment(SwingConstants.CENTER);
		add(lblOrt);
		
		venueField = new JComboBox<String>();
		venueField.setModel(new DefaultComboBoxModel<String>(new String[] {"Hello ", "My", "Stupid", "REWE"}));
		venueField.setEditable(true);
		controller.getModel().getDataSource().getPopularVenues();
		add(venueField);
		
		JLabel lblDatum = new JLabel("Datum (TT/MM/YYYY)");
		lblDatum.setHorizontalAlignment(SwingConstants.CENTER);
		add(lblDatum);
		
		
		
		JPanel dateSpinners = new JPanel();
		daySpinner = new JSpinner();		
		dateSpinners.add(daySpinner);
		
		monthSpinner = new JSpinner(new SpinnerListModel(controller.getMonthArray()));		
		dateSpinners.add(monthSpinner);
		
		yearSpinner = new JSpinner();		
		dateSpinners.add(yearSpinner);
		updateCalendar();
		
		
		
		add(dateSpinners);
		
		JLabel lblBetrag = new JLabel("Betrag");
		lblBetrag.setHorizontalAlignment(SwingConstants.CENTER);
		add(lblBetrag);
		
		amountSpinner = new JSpinner();
		amountSpinner.setModel(new SpinnerNumberModel(new Double(1), new Double(0), null, new Double(1)));
		add(amountSpinner);
		
		JLabel lblKonto = new JLabel("Konto");
		lblKonto.setHorizontalAlignment(SwingConstants.CENTER);
		add(lblKonto);
		
		accountComboBox = new JComboBox<String>();
		accountBoxModel = new DefaultComboBoxModel<String>();
		accountComboBox.setModel(accountBoxModel);
		add(accountComboBox);
		
		JButton btnBuchen = new JButton("Buchen");
		btnBuchen.setActionCommand("add#transaction");
		btnBuchen.addActionListener(controller);
		
		lblZielkonto = new JLabel("Zielkonto");
		add(lblZielkonto);
		
		targetAccountBox = new JComboBox<String>();
		targetAccountBoxModel = new DefaultComboBoxModel<String>();
		targetAccountBox.setModel(targetAccountBoxModel);
		parseAccounts();
		add(targetAccountBox);
		
		lblBemerkung = new JLabel("Bemerkung");
		add(lblBemerkung);
		
		commentComboBox = new JComboBox<String>();
		commentComboBoxModel = new DefaultComboBoxModel<String>(new String[] {"Nutzloser", "Wichser", "Spasst", "Pisser", "Dreckssack", "Norbert"});
		commentComboBox.setModel(commentComboBoxModel);
		commentComboBox.setSelectedIndex(5);
		commentComboBox.setEditable(true);
		add(commentComboBox);
		add(btnBuchen);

		rdbtnAusgabe.addChangeListener(rdbtnListener);
		rdbtnEinkommen.addChangeListener(rdbtnListener);
		rdbtnUmbuchung.addChangeListener(rdbtnListener);
		switchForm(true, false, false);
	}

	protected void switchForm(boolean isExpense, boolean isIncome, boolean isTransfer) {
		lblKategorie.setVisible(isExpense);
		categoryBox.setVisible(isExpense);
		
		lblOrt.setVisible((isExpense || isIncome));
		venueField.setVisible((isExpense || isIncome));
		
		lblZielkonto.setVisible(isTransfer);
		targetAccountBox.setVisible(isTransfer);
		
		lblBemerkung.setVisible(isTransfer);
		commentComboBox.setVisible(isTransfer);
	}

	private void updateCalendar() {
		Calendar now = Calendar.getInstance();
		daySpinner.setValue(now.get(Calendar.DAY_OF_MONTH));
		
		String month = controller.getMonthArray()[now.get(Calendar.MONTH)];
		monthSpinner.setValue(month);
		yearSpinner.setValue(now.get(Calendar.YEAR));
	}

	private void parseAccounts() {
		accountBoxModel.removeAllElements();
		targetAccountBoxModel.removeAllElements();
		
		LinkedList<String> accounts = controller.getModel().getDataSource().getAccounts();
		
		for (String account : accounts) {
			accountBoxModel.addElement(account);
			targetAccountBoxModel.addElement(account);
		}
		
		accountBoxModel.setSelectedItem(accounts.get(controller.getModel().getDataSource().getDefaultAccount()));
		targetAccountBoxModel.setSelectedItem(accounts.get(controller.getModel().getDataSource().getDefaultAccount()));		
	}

	private void parseCategories() {
		categoryBoxModel.removeAllElements();
		LinkedList<String> categories = controller.getModel().getDataSource().getCategories();
		
		for (String category : categories) {
			categoryBoxModel.addElement(category);
		}
		
		categoryBoxModel.setSelectedItem(categories.get(controller.getModel().getDataSource().getDefaultCategory()));
	}

	public void processForm(Model model) {
		DataSource src = model.getDataSource();
		
		double amount = Double.parseDouble(amountSpinner.getValue().toString());
		int account = src.getAccounts().indexOf(accountBoxModel.getSelectedItem());
		String venue = venueField.getSelectedItem().toString();
		
		int year = Integer.parseInt(yearSpinner.getValue().toString());		
		int month = controller.getIndexOf(monthSpinner.getValue().toString());
		System.out.println("our month is:"+month);
		int day = Integer.parseInt(daySpinner.getValue().toString());
		
		// switch type
		if(rdbtnAusgabe.isSelected()) { // process expense			
			int category = src.getCategories().indexOf(categoryBoxModel.getSelectedItem());			
			Expense expense = new Expense(amount, account, venue, category, year, month, day);			
			model.addExpense(expense);			
		}
		else if(rdbtnEinkommen.isSelected()) {
			venue = commentComboBox.getSelectedItem().toString();
			Income income = new Income(amount, account, venue, year, month, day);
			model.addIncome(income);
		}
		else if(rdbtnUmbuchung.isSelected()) {
			int targetAccount = src.getAccounts().indexOf(targetAccountBoxModel.getSelectedItem());
			System.out.println("target account:"+targetAccount);
			Transfer transfer = new Transfer(amount, account, targetAccount, venue, year, month, day);
			model.addTransfer(transfer);
		}
		
	}

	public void reset() {
		parseCategories();
		//TODO parse venues // and venues of transfers
		updateCalendar();
		amountSpinner.setValue(1); // TODO approx. val
		accountBoxModel.setSelectedItem(controller.getModel().getDataSource().getAccounts().get(controller.getModel().getDataSource().getDefaultAccount()));
		
		
	}

}
